#include "Avalon/CodecsTests/CodedReaderTester.hpp"
#include "Avalon/IO/Buffer.hpp"
#include "Avalon/IO/BufferReader.hpp"
#include "Avalon/IO/EndOfFileException.hpp"
#include "Avalon/Codecs/CodedReader.hpp"
#include "Avalon/CodecsTests/ReverseDecoder.hpp"

using namespace Avalon;
using namespace Avalon::Codecs;
using namespace Avalon::Codecs::Tests;
using namespace Avalon::IO;
using namespace Avalon::Threading;
using namespace boost;
using namespace boost::posix_time;
using namespace std;

void CodedReaderTester::TestEmpty() {
  BufferReader bufferReader(BufferFromString(""));
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  Async<int> readResult;
  Buffer buffer;
  codedReader.Read(&buffer, Store(readResult));
  CPPUNIT_ASSERT_THROW(readResult.Get(), EndOfFileException);
}

void CodedReaderTester::TestSingleByte() {
  BufferReader bufferReader(BufferFromString("a"));
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  Async<int> readResult;
  Buffer buffer;
  codedReader.Read(&buffer, Store(readResult));
  CPPUNIT_ASSERT(readResult.Get() == 1);
  CPPUNIT_ASSERT(buffer.GetSize() == 1);
  CPPUNIT_ASSERT(buffer.GetData()[0] == 'a');
  readResult.Reset();
  codedReader.Read(&buffer, Store(readResult));
  CPPUNIT_ASSERT_THROW(readResult.Get(), EndOfFileException);
}

void CodedReaderTester::TestRead() {
  string message = "hello world";
  string reverse = "dlrow olleh";
  BufferReader bufferReader(BufferFromString(message));
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  Async<int> readResult;
  Buffer buffer;
  codedReader.Read(&buffer, Store(readResult));
  CPPUNIT_ASSERT(readResult.Get() == static_cast<int>(reverse.size()));
  CPPUNIT_ASSERT(buffer.GetSize() == static_cast<int>(reverse.size()));
  CPPUNIT_ASSERT(string(buffer.GetData(), buffer.GetSize()) == reverse);
  readResult.Reset();
  codedReader.Read(&buffer, Store(readResult));
  CPPUNIT_ASSERT_THROW(readResult.Get(), EndOfFileException);
}

void CodedReaderTester::TestReadSome() {
  string message = "helloworld";
  string firstReverse = "dlrow";
  string secondReverse = "olleh";
  BufferReader bufferReader(BufferFromString(message));
  CodedReader codedReader(bufferReader, new ReverseDecoder());
  Async<int> readResult;
  Buffer buffer;
  codedReader.Read(&buffer, static_cast<int>(firstReverse.size()),
    Store(readResult));
  CPPUNIT_ASSERT(readResult.Get() == static_cast<int>(firstReverse.size()));
  CPPUNIT_ASSERT(buffer.GetSize() == static_cast<int>(firstReverse.size()));
  CPPUNIT_ASSERT(string(buffer.GetData(), buffer.GetSize()) == firstReverse);
  buffer.Reset();
  readResult.Reset();
  codedReader.Read(&buffer, static_cast<int>(secondReverse.size()),
    Store(readResult));
  CPPUNIT_ASSERT(readResult.Get() == static_cast<int>(secondReverse.size()));
  CPPUNIT_ASSERT(buffer.GetSize() == static_cast<int>(secondReverse.size()));
  CPPUNIT_ASSERT(string(buffer.GetData(), buffer.GetSize()) == secondReverse);
  readResult.Reset();
  codedReader.Read(&buffer, Store(readResult));
  CPPUNIT_ASSERT_THROW(readResult.Get(), EndOfFileException);
}
